package com.entrogy.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.entrogy.api.ThdidPersonApi;
import com.entrogy.bean.*;
import com.entrogy.service.*;
import com.entrogy.timing.ChangePersonTimeThread;
import com.entrogy.timing.TimingTaskService;
import com.entrogy.utils.*;
import com.entrogy.utils.constants.Constants;
import com.entrogy.utils.constants.ErrorEnum;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @ClassName ParentController
 * @Description
 * @Author luoxingjiang
 * @Date 2019/7/24 0024 下午 5:17
 * @Version 1.0
 **/
@RestController
@RequestMapping("/parent")
@Api(description = "家长相关操作接口")
public class ParentController {

    private static final Logger logger = LoggerFactory.getLogger(ParentController.class);

    @Autowired
    private StudentService studentService;

    @Autowired
    private ParentService parentService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private UserService userService;

    @Autowired
    private SchoolService schoolService;

    @Autowired
    private PositionService positionService;

    @Autowired
    private ClassService classService;

    @Autowired
    private ThdidPersonApi thdidPersonApi;

    @Value("${show.image.url}")
    private String showImage;

    @Value("${image.root.path}")
    private String baseImage;

    @ApiOperation(value = "查询家长预留电话号码")
    @ApiImplicitParams({
        @ApiImplicitParam(name="invitationCode",value = "邀请码",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="studentName",value = "学生姓名",dataType = "String",paramType = "query"),
    })
    @GetMapping(value = "/listParentPhones")
    public Msg listParentPhones(String invitationCode, String studentName){
        // TODO 校验家长更改哪位学生的家长信息的规则为暂时只通过学生名字
        // 根据邀请码查询有没有该学生
        Map<String, Integer> schoolCodeAndClassId = readInvitationCode(invitationCode);
        if (schoolCodeAndClassId == null){
            return Msg.fail(ErrorEnum.E_101, "邀请码错误，请重新输入！");
        }
        Integer schoolCode = schoolCodeAndClassId.get("schoolCode");
        Integer classId = schoolCodeAndClassId.get("classId");
        //根据schoolCode和classId去查询该学生
        Integer studentId = studentService.findStudentBySchoolCodeAndClassId(schoolCode, classId, studentName);
        if (studentId == null){
            return Msg.fail(ErrorEnum.E_101,"邀请码或学生姓名错误，请重新输入！");
        }
        //查看该学生的所有家长的联系方式
        List<JSONObject> parentInfos = parentService.ListParentPhonesByStudentId(studentId);
        return Msg.success().add("parentInfos", parentInfos).add("studentId", studentId);
    }

    @ApiOperation(value = "家长提交修改预留电话号码的申请给班主任")
    @ApiImplicitParams({
        @ApiImplicitParam(name="parentId",value = "家长id",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="newPhone",value = "家长的新手机号",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="invitationCode",value = "邀请码",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="studentId",value = "学生id",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="verifyCodeId",value = "验证码id",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="verifyCode",value = "验证码",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="weiXinInfoId",value = "手机号码和openid对应id",dataType = "Integer",paramType = "query"),
    })
    @PostMapping(value = "/parentPhoneChangeOffer")
    public Msg parentPhoneChange(String parentId, String newPhone, String invitationCode, Integer studentId, Integer verifyCodeId, Integer verifyCode, Integer weiXinInfoId){
        if (!compareVerifyCode(verifyCodeId, verifyCode)){
            return Msg.fail(ErrorEnum.E_101, "验证码错误，请重新输入！");
        }
        // 家长申请信息修改时首先查询有没有待审核的申请
        Integer flag = 1; //1表示待审核
        boolean hasToAudit = parentService.hasToAudit(parentId, flag);
        if (hasToAudit){
            return Msg.fail(ErrorEnum.E_101, "对不起，您已经有一条信息变更记录在待审核状态，请联系班主任审核通过再次提交，谢谢！");
        }
        // 以上根据邀请码可以确定唯一的学生id，就是这个家长在这个学校对应的班级的孩子，他的修改申请会提交给唯一的这个孩子的班主任
        // 查询应该处理该申请的班主任的id
        Map<String, Integer> schoolCodeAndClassId = readInvitationCode(invitationCode);
        if (schoolCodeAndClassId == null){
            return Msg.fail(ErrorEnum.E_101, "邀请码错误，请重新输入！");
        }
        TeacherBasicInfoEntity teacher = userService.getTeacherIdByClassId(schoolCodeAndClassId);

        ParentInformationChangeEntity parentPhoneChangeRecord = new ParentInformationChangeEntity();
        parentPhoneChangeRecord
                .setParentVisitorId(parentId)
                .setNewPhone(newPhone)
                .setTeacherId(teacher.getTeacherId())
                .setStudentId(studentId)
                .setChangeType(0)
                .setAgreed(1)
                .setWeiXinInfoId(weiXinInfoId);
        // 将该条申请存入数据库并通知班主任
        boolean result = parentService.insertParentPhoneChangeRecord(parentPhoneChangeRecord);
        if (!result){
            return Msg.fail(ErrorEnum.E_101, "审核数据插入失败");
        }
        sendInformationChangeMessage(teacher, "家长");
        return Msg.success().add("teacherPhone", teacher.getMobile());
    }


    @ApiOperation(value = "班主任查看该班所有学生列表以及其家长信息变更状态")
    @ApiImplicitParams({
        @ApiImplicitParam(name="uid",value = "用户id",dataType = "String",paramType = "query"),
    })
    @GetMapping(value = "/listStudentAndInformationStatus")
    public Msg listStudentAndInformationStatus(String uid){
        boolean isClassLeader = positionService.checkPosition(uid, 16);
        // 首先查询出学生列表以及其是否有家长信息变更申请
        List<JSONObject> studentInformationList;
        if (isClassLeader){
            //将showImage传入拼接回显地址
            studentInformationList = studentService.listStudentAndInformationStatus(uid, showImage);
        }else {
            return Msg.fail(ErrorEnum.E_101, "对不起，您没有权限！");
        }
        // 根据班主任id查询邀请码以及班级名称
        JSONObject classInfo = userService.getClassInfo(uid);
        return Msg.success().add("studentInformationList", studentInformationList).add("classInfo", classInfo);
    }

    @ApiOperation(value = "查询家长信息以及孩子信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name="uid",value = "用户id",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="studentId",value = "学生id",dataType = "Integer",paramType = "query"),
    })
    @GetMapping(value = "/getParentAndChildInformation")
    public Msg getParentAndChildInformation(String uid, Integer studentId){
        if (StrUtils.isNullOrEmpty(uid)){
            return Msg.fail(ErrorEnum.E_101, "对不起，您尚未登录！");
        }
        //如果是家长，则根据家长id查询该家长以及孩子的信息
        if (uid.startsWith("3")){
            ParentVisitorEntity parent = parentService.getparentById(uid);
            //查看该家长是否有处于待审核的信息
            String parentId = parent.getParentVisitorId();
            JSONObject informationChangeList = parentService.getParentInformationChangeList(parentId);
            if (informationChangeList != null){
                parent.setInformationChangeList(informationChangeList);
                parent.setHasChecked(true);
                //设置家长新的的图片回显地址
                String newImageUrl = informationChangeList.getString("newImageUrl");
                if (!StrUtils.isNullOrEmpty(newImageUrl)){
                    informationChangeList.put("newImageUrl", showImage + File.separator + newImageUrl);
                }
            }
            //设置家长原来的图片回显地址
            parent.setParentVisitorBase64(showImage + File.separator + parent.getParentVisitorBase64());

            //将家长实体存入list
            List<ParentVisitorEntity> parentList = new ArrayList<>();
            parentList.add(parent);
            List<StudentEntity> studentList = parentService.getStudentByParentId(uid);

            //设置学生图片回显地址
            for (StudentEntity student : studentList) {
                student.setStudentBase64(showImage + File.separator + student.getStudentBase64());
            }

            return Msg.success().add("parentList", parentList).add("studentList", studentList);
        }else if (uid.startsWith("1")){
            StudentEntity student = studentService.getStudentById(studentId);
            //设置学生图片回显地址
            student.setStudentBase64(showImage + File.separator + student.getStudentBase64());
            //将学生实体存入list
            List<StudentEntity> studentList = new ArrayList<>();
            studentList.add(student);
            List<ParentVisitorEntity> parentList = parentService.listParentByStudentId(studentId);
            //查询这些家长的信息变更记录
            for (ParentVisitorEntity parentVisitorEntity : parentList) {
                String parentId = parentVisitorEntity.getParentVisitorId();
                JSONObject informationChangeList = parentService.getParentInformationChangeList(parentId);
                if (informationChangeList != null){
                    //设置家长新的的图片回显地址
                    String newImageUrl = informationChangeList.getString("newImageUrl");
                    if (!StrUtils.isNullOrEmpty(newImageUrl)){
                        informationChangeList.put("newImageUrl", showImage + File.separator + newImageUrl);
                    }
                    parentVisitorEntity.setInformationChangeList(informationChangeList);
                }
                //设置家长图片回显地址
                parentVisitorEntity.setParentVisitorBase64(showImage + File.separator + parentVisitorEntity.getParentVisitorBase64());
            }
            //查询这个学生的家长新增记录
            List<ParentInformationChangeEntity> parentAddList = parentService.listAddParentInformation(student.getId());
            return Msg.success().add("parentList", parentList).add("studentList", studentList).add("parentAddList", parentAddList);
        }
        return Msg.fail(ErrorEnum.E_101, "对不起，您没有权限！");
    }

    @ApiOperation(value = "家长提交修改个人信息的申请给班主任")
    @ApiImplicitParams({
        @ApiImplicitParam(name="parentId",value = "家长id",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="newParentName",value = "新家长姓名",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="newPhone",value = "新家长电话号码",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="newImageUrl",value = "新图片地址",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="verifyCodeId",value = "验证码id",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="verifyCode",value = "验证码",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="weiXinInfoId",value = "手机号码和openid对应id",dataType = "Integer",paramType = "query"),
    })
    @PostMapping(value = "/parentInformationChangeOffer")
    public Msg parentPhoneChange(String parentId, String newParentName, String newPhone, String newImageUrl, Integer verifyCodeId, Integer verifyCode, Integer weiXinInfoId){
        boolean compareVerifyCodeResult;
        if (verifyCode != null && verifyCodeId != null){
            compareVerifyCodeResult = compareVerifyCode(verifyCodeId, verifyCode);
            if (!compareVerifyCodeResult){
                return Msg.fail(ErrorEnum.E_101, "验证码错误，请重新输入！");
            }
        }
        //家长申请信息修改时首先查询有没有待审核的申请
        Integer flag = 1; //1表示待审核
        boolean hasToAudit = parentService.hasToAudit(parentId, flag);
        if (hasToAudit){
            return Msg.fail(ErrorEnum.E_101, "对不起，您已经有一条信息变更记录在待审核状态，请联系班主任审核通过再次提交，谢谢！");
        }
        //这里是家长在小程序页面的信息维护功能，没有邀请码可以确定唯一的学生id，那么就先根据家长id去只查询一个老师出来，
        TeacherBasicInfoEntity teacher = userService.getTeacherIdByParentId(parentId, null, null);
        if (teacher == null){
            return Msg.fail(ErrorEnum.E_101, "对不起，您的孩子没有班主任，暂时不能修改信息！");
        }
        //然后根据老师id和家长id去确定一个学生id
        Integer studentId = studentService.getStudentIdByParentIdAndTeacherId(parentId, teacher.getTeacherId());
        //根据家长和老师id去查询唯一的学生id
        ParentInformationChangeEntity parentInformation = new ParentInformationChangeEntity();
        //changeType的值0为修改，1为注册/新增,agreed的值1为审核，2为审核通过，3为审核不通过
        parentInformation
                .setNewParentName(newParentName)
                .setNewPhone(newPhone)
                .setNewImageUrl(newImageUrl)
                .setTeacherId(teacher.getTeacherId())
                .setStudentId(studentId)
                .setParentVisitorId(parentId)
                .setChangeType(0)
                .setAgreed(1)
                .setWeiXinInfoId(weiXinInfoId);
        boolean result = parentService.insertParentPhoneChangeRecord(parentInformation);
        if (!result){
            return Msg.fail(ErrorEnum.E_101, "审核数据插入失败");
        }
        sendInformationChangeMessage(teacher, "家长");
        return Msg.success();
    }

//    @ApiOperation(value = "家长提交修改学生信息的申请给班主任，此接口暂时不调用") // TODO 暂时不用此接口
//    @ApiImplicitParams({
//            @ApiImplicitParam(name="parentId",value = "家长id",dataType = "String",paramType = "query"),
//            @ApiImplicitParam(name="studentId",value = "学生id",dataType = "Integer",paramType = "query"),
//            @ApiImplicitParam(name="newStudentName",value = "新学生姓名",dataType = "String",paramType = "query"),
//            @ApiImplicitParam(name="newImageUrl",value = "新图片地址",dataType = "String",paramType = "query"),
//    })
//    @PostMapping(value = "/studentInformationChangeOffer")
//    public Msg parentPhoneChange(@ModelAttribute StudentInformationChangeEntity studentNewInformation){
//        //查找学生信息
//        StudentEntity student = studentService.getStudentById(studentNewInformation.getStudentId());
//        Integer schoolCode = student.getSchoolCode();
//        Integer classId = student.getCourseId();
//        TeacherEntity teacher = userService.getTeacherIdByParentId(studentNewInformation.getParentId(), schoolCode, classId);
//        studentNewInformation.setTeacherId(teacher.getTeacherId());
//        boolean result = parentService.insertStudentPhoneChangeRecord(studentNewInformation);
//        if (!result){
//            return Msg.fail(ErrorEnum.E_101, "审核数据插入失败");
//        }
//        sendInformationChangeMessage(teacher, "学生");
//        return Msg.success();
//    }

    @ApiOperation(value = "根据信息变更id查询具体的变更字段")
    @ApiImplicitParams({
        @ApiImplicitParam(name="changeId",value = "信息变更id",dataType = "Integer",paramType = "query"),
    })
    @GetMapping(value = "/getChangeDetail")
    public Msg getChangeDetail(Integer changeId){
        JSONObject changeList = parentService.getParentInformationChangeDetail(changeId);
        return Msg.success().add("changeList", changeList);
    }

    @ApiOperation(value = "班主任审核家长的信息修改/注册申请")
    @ApiImplicitParams({
        @ApiImplicitParam(name="teacherId",value = "教师id",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="changeId",value = "信息变更id",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="agreed",value = "同意与否，2为同意，3为不同意",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="changeType",value = "0为审核修改信息，1为审核新增信息",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="studentId",value = "学生id",dataType = "Integer",paramType = "query"),
    })
    @PostMapping(value = "/checkParentInformationChange")
    public Msg checkParentInformationChange(String teacherId, Integer changeId, Integer agreed, Integer changeType, Integer studentId){
        boolean isClassLeader = positionService.checkPosition(teacherId, 16);
        if (!isClassLeader){
            return Msg.fail(ErrorEnum.E_101, "对不起，您没有权限！");
        }
        // 查询该该条信息的变更/新增字段
        JSONObject changeInfo = parentService.getParentInformationChangeDetail(changeId);
        String newPhone = changeInfo.getString("newPhone");
        String newImageUrl = changeInfo.getString("newImageUrl");
        String newParentName = changeInfo.getString("newParentName");
        // 短信内容
        String content = "";
        // 根据通知的标志位判断是审核成功还是审核不通过
        if (agreed.equals(3)){
            if (changeType.equals(0)){
                content = "您在脸卡通智慧校园系统内的信息修改申请没有通过审核，请修改后重新提交";
            }else if(changeType.equals(1)){
                content = "您在脸卡通智慧校园系统的注册申请没有通过审核，请修改后重新提交";
            }
        }else if (agreed.equals(2)){
            // 审核通过，更新该家长的数据
            if (changeType.equals(0)){
                String parentId = changeInfo.getString("parentId");
                ParentVisitorEntity parentFromDB = parentService.getparentById(parentId);
                ParentVisitorEntity parentVisitorEntity = new ParentVisitorEntity(parentId, newParentName, newPhone, newImageUrl);
                // 判断是否在更新号码
                if (newPhone != null && !newPhone.equals(parentService.getparentById(parentId).getParentVisitorPhone())){
                    // 当家长自主修改电话号码时，不管有没有多个孩子，改自己信息就完事了
//                    boolean hasMultipleChild = false;
//                    List<StudentBasicInfoEntity> studentList = parentService.listStudentByParentId(parentId);
//                    if (studentList.size() > 1){
//                        hasMultipleChild = true;
//                    }
                    Integer parentCount = parentService.countParent(studentId);
//                    if (!hasMultipleChild){
                        ParentVisitorEntity temp = parentService.getParentByPhone(newPhone);
                        int code;
                        // 更改电话号码分两种情况
                        // ① 更改的电话号码在我们库里已经注册为家长（需要建立这个电话号码对应的家长id和学生的关系）
                        if (temp != null){
                            Map<String, Object> map = new HashMap<>();
                            map.put("id", studentId);
                            map.put("parent_id", temp.getParentVisitorId());
                            map.put("type", parentCount == 0 ? 1 : 2);
                            code = studentService.updateStuent1(map);
                        }else {
                            // ② 更改的电话号码在我们库里面不是家长（直接更改即可）
                            code = parentService.updateParent(parentVisitorEntity);
                        }
//                    }else {
//                        parentVisitorEntity.setParentVisitorType(parentCount == 0 ? 1 : 2);
//                        parentVisitorEntity.setParentVisitorName(parentFromDB.getParentVisitorName());
//                        addParent(studentId, parentVisitorEntity);
//                    }
                }else {
                    boolean updateParentResult = parentService.updateParentDetail(newParentName, newImageUrl, parentId);
                    if (!updateParentResult){
                        return Msg.fail(ErrorEnum.E_101, "更改家长基本信息出错，请联系管理员！");
                    }
                }
                // 如果电话号码有修改，那么要解绑原手机号和当前家长使用微信的关系
                if (!StrUtils.isNullOrEmpty(newPhone)){
                    boolean cancelBindResult = parentService.weiXinBindNewPhone(changeInfo.getInteger("weiXinInfoId"), newPhone);
                    if (!cancelBindResult){
                        // 此处家长可能没有登录小程序，可能解绑失败
//                        return Msg.fail(ErrorEnum.E_101, "微信号解绑失败！");
                        logger.info("家长=>" + parentVisitorEntity.getParentVisitorId() + "在信息更新时，微信解绑失败！");
                    }
                }
                content = "您在脸卡通智慧校园系统内的信息修改申请已经通过审核！";
            } else if (changeType.equals(1)){
                // 审核通过，注册该家长的数据
                Integer parentCount = parentService.countParent(studentId);
                // type为1就是家长1，为2就是家长2
                ParentVisitorEntity parentVisitorEntity = new ParentVisitorEntity(null, newParentName, newPhone, newImageUrl);
                parentVisitorEntity.setParentVisitorType(parentCount == 0 ? 1 : 2);
                Integer schoolCode = userService.getSchoolCodeByUserId(teacherId);
                parentVisitorEntity.setParentVisitorStudentId(studentId);
                parentVisitorEntity.setParentVisitorSchoolCode(schoolCode);
                addParent(studentId, parentVisitorEntity);
                content = "您在脸卡通智慧校园系统的注册申请已经通过审核！";
            }
        }
        // 然后短信通知家长信息修改审核是否通过，有新号码发送新号码，没有新号码发送给旧号码
        JSONObject parentInformationChangeDetail = parentService.getParentInformationChangeDetail(changeId);
        // 班主任拒绝或同意了家长的信息修改，修改该条数据的状态
        boolean result = parentService.updateChangeRecord(changeId, agreed);
        if (parentInformationChangeDetail.getString("newPhone") != null){
            // TODO 暂时使用的短信模板id为message_template内的默认模板
            sendToPerson(parentInformationChangeDetail.getString("newPhone"), "224729", content);
        }else {
            ParentVisitorEntity parent = parentService.getparentById(parentInformationChangeDetail.getString("parentId"));
            sendToPerson(parent.getParentVisitorPhone(), "224729", content);
        }
        return Msg.success();
    }

    @ApiOperation(value = "小程序端教师修改家长信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name="parentId",value = "家长id",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="newPhone",value = "家长新电话号码",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="newParentName",value = "家长新名字",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="newImageUrl",value = "家长新照片",dataType = "String",paramType = "query"),
    })
    @PutMapping(value = "/updateParentInformation")
    public Msg updateParentInformation(String parentId, String newPhone, String newParentName, String newImageUrl){
        ParentVisitorEntity temp = parentService.getParentByPhone(newPhone);
        if (temp != null){
            return Msg.fail(ErrorEnum.E_101, "对不起，新手机号码已经注册为家长！");
        }
        ParentVisitorEntity parentVisitorEntity = new ParentVisitorEntity(parentId, newParentName, newPhone, newImageUrl);
        int row = parentService.updateParent(parentVisitorEntity);
        if (row == 1){
            return Msg.success();
        }
        return Msg.fail(ErrorEnum.E_101, "家长信息更新失败！");
    }

    @ApiOperation(value = "小程序端教师修改学生信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name="studentId",value = "学生id",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="newStudentName",value = "学生新名字",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="newImageUrl",value = "学生新照片",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="uid",value = "教师id",dataType = "String",paramType = "query"),
    })
    @PutMapping(value = "/updateStudentInformation")
    public Msg updateStudentInformation(Integer studentId, String newStudentName, String newImageUrl, String uid){
        // 修改我们库里的学生信息
        Integer schoolCode = userService.getSchoolCodeByUserId(uid);
        StudentEntity studentEntity = studentService.getStudentById(studentId);
        studentEntity.setStudentName(newStudentName);
        studentEntity.setStudentBase64(newImageUrl);
        int row = studentService.updateStudent(studentEntity);
        // 修改实义德后台的学生信息
        StudentBaseEntity studentToThdid = new StudentBaseEntity();
        studentToThdid.setPhotoUrl(newImageUrl).setStudentName(newStudentName).setStudentId(studentId);
        // 如果修改了照片或者姓名，那么需要修改实义德后台的照片
        Map<String, Integer> thdidInfo = thdidPersonApi.updateStudentToAll(studentToThdid, schoolCode);
        // 修改可能会新增，所以直接更新学生的实义德后台id
        studentService.updateStudentAllThdid(studentId, thdidInfo);
        return Msg.success();
    }

    @ApiOperation(value = "验证码发送接口")
    @ApiImplicitParams({
        @ApiImplicitParam(name="phone",value = "手机号码",dataType = "String",paramType = "query"),
    })
    @PutMapping(value = "/sendVerifyCode")
    public Msg sendVerifyCode(String phone){
        // 当前系统当存在一个家长是多个孩子的家长的情况时，暂时只支持一个孩子对应一个家长电话号码
        ParentVisitorEntity temp = parentService.getParentByPhone(phone);
        if (temp != null){
            return Msg.fail(ErrorEnum.E_101, "该账号已注册为家长，请直接登录！");
        }
        //判断注册的手机号是否处于注册或修改的申请程序中
        JSONObject checkInfo = parentService.checkParentPhoneStatus(phone);
        if (checkInfo != null){
            return Msg.fail(ErrorEnum.E_101, "对不起,该账号正在审核中").add("teacherPhone", checkInfo.getString("teacherPhone")).add("changeType", checkInfo.getString("changeType"));
        }
        // 生成4为随机数
        int randNum = (int) ((Math.random() * 9 + 1) * 1000);
        //将验证码存储起来
        VerifyCodeEntity verifyCodeEntity = new VerifyCodeEntity();
        verifyCodeEntity.setPhone(phone).setVerifyCode(randNum);
        Integer verifyCodeId = parentService.insertVerifyCode(verifyCodeEntity);
        if (verifyCodeId != null){
            String[] params = { randNum + "" };
            SendUtils.sendByShortMessage(phone, params, 368358 + "");
        }
        return Msg.success().add("verifyCodeId", verifyCodeId);
    }

    @ApiOperation(value = "家长信息注册接口")
    @ApiImplicitParams({
        @ApiImplicitParam(name="studentName",value = "学生姓名",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="parentPhone",value = "家长电话号码",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="invitationCode",value = "邀请码",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="verifyCodeId",value = "验证码id",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="verifyCode",value = "验证码",dataType = "Integer",paramType = "query"),
    })
    @PutMapping(value = "/parentRegister")
    public Msg parentRegister(String parentPhone, String studentName, String invitationCode, Integer verifyCodeId, Integer verifyCode){
        if (!compareVerifyCode(verifyCodeId, verifyCode)){
            return Msg.fail(ErrorEnum.E_101, "验证码错误，请重新输入！");
        }
        //判断注册的账号是否已存在
        ParentVisitorEntity parent = parentService.getParentByPhone(parentPhone);
        if (parent != null){
            return Msg.fail(ErrorEnum.E_101, "该账号已注册为家长，请直接登录！");
        }
        //查询应该处理该申请的班主任的id
        Map<String, Integer> schoolCodeAndClassId = readInvitationCode(invitationCode);
        if (schoolCodeAndClassId == null){
            return Msg.fail(ErrorEnum.E_101, "邀请码错误，请重新输入！");
        }
        TeacherBasicInfoEntity teacher = userService.getTeacherIdByClassId(schoolCodeAndClassId);
        // TODO 根据班级id和学生名字确定一个学生id不合理，暂时这样处理
        Integer classId = schoolCodeAndClassId.get("classId");
        Integer schoolCode = schoolCodeAndClassId.get("schoolCode");
        List<Integer> studentIdList = studentService.getStudentId(studentName, classId, schoolCode);
        if (studentIdList.size() != 1){
            if (studentIdList.size() == 0){
                return Msg.fail(ErrorEnum.E_101, "对不起，该班级没有该学生，请联系脸卡通客服！");
            }else {
                return Msg.fail(ErrorEnum.E_101, "对不起，该班级有两个同名学生不能进行此操作，请联系脸卡通客服！");
            }
        }
        Integer studentId = studentIdList.get(0);
        if(teacher != null){
            //向班主任发送家长的注册申请
            sendInformationChangeMessage(teacher, "家长");
        }
        ParentInformationChangeEntity parentInformationChange = new ParentInformationChangeEntity();
        //将家长在小程序页面的注册申请默认设置一个家长姓名，格式为学生名+“家长” //如果该生没有家长，则第一个家长为家长1，第二个家长为家长2
        Integer parentCount = parentService.countParent(studentId);
        String parentName;
        if (parentCount.equals(0)){
            parentName = studentName + "家长1";
        }else if (parentCount.equals(1)){
            parentName = studentName + "家长2";
        }else {
            return Msg.fail(ErrorEnum.E_101, "该学生已经添加了两个家长，不能再次添加！");
        }
        //新增申请，changeType为1
        parentInformationChange
                .setNewPhone(parentPhone)
                .setTeacherId(teacher.getTeacherId())
                .setChangeType(1)
                .setAgreed(1)
                .setStudentId(studentId)
                .setNewParentName(parentName);
        boolean result = parentService.insertParentPhoneChangeRecord(parentInformationChange);
        if (result){
            return Msg.success().add("teacherPhone", teacher.getMobile());
        }
        return Msg.fail(ErrorEnum.E_101, "审核数据更新失败");
    }

    @ApiOperation(value = "微信号和手机号码解绑")
    @ApiImplicitParams({
        @ApiImplicitParam(name="id",value = "手机号码和openid对应id",dataType = "Integer",paramType = "query"),
    })
    @PutMapping(value = "/cancelWeiXinAndPhoneBind")
    public Msg cancelWeiXinAndPhoneBind(Integer id){
        //将传过来的id设置相应记录的电话为空，登录时再次与电话号码绑定
        boolean result = parentService.cancelWeiXinAndPhoneBind(id);
        if (result)
            return Msg.success();
        return Msg.fail(ErrorEnum.E_101, "解绑失败");
    }

    private boolean compareVerifyCode(Integer id, Integer verifyCode){
        boolean result = parentService.compareVerifyCode(id, verifyCode);
        return result;
    }

    @ApiOperation(value = "查询某个班级的家长")
    @ApiImplicitParams({
        @ApiImplicitParam(name="uid",value = "用户id",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="classId",value = "班级id",dataType = "Integer",paramType = "query"),
    })
    @GetMapping(value = "/list-class-parent")
    public Msg listClassParent(String uid, Integer classId){
        Integer schoolCode = userService.getSchoolCodeByUserId(uid);
        List<ParentVisitorEntity> parentList = parentService.listClassParent(schoolCode, classId);
        return Msg.success().add("parentList", parentList).add("showImage", showImage);
    }

    @ApiOperation(value = "查询某个学校的所有班级")
    @ApiImplicitParams({
        @ApiImplicitParam(name="uid",value = "用户id",dataType = "String",paramType = "query"),
        @ApiImplicitParam(name="gradeId",value = "年级",dataType = "Integer",paramType = "query"),
        @ApiImplicitParam(name="classId",value = "班级",dataType = "Integer",paramType = "query"),
    })
    @GetMapping(value = "/list-class")
    public Msg listClass(String uid, Integer gradeId, Integer classId){
        Integer schoolCode = userService.getSchoolCodeByUserId(uid);
        List<ParentClassEntity> parentClassList = parentService.listClass(schoolCode, gradeId, classId);
        return Msg.success().add("parentClassList", parentClassList);
    }

    @ApiOperation(value = "查询某个家长的学生列表")
    @ApiImplicitParams({
        @ApiImplicitParam(name="uid", value = "用户id", dataType = "String", paramType = "query"),
    })
    @GetMapping(value = "/list-parent-student")
    public Msg listParentStudent(String uid){
        List<StudentBasicInfoEntity> parentStudentList = parentService.listStudentByParentId(uid);
        return Msg.success().add("parentStudentList", parentStudentList);
    }

    @ApiOperation(value = "查询某个家长小程序登录情况")
    @ApiImplicitParams({
            @ApiImplicitParam(name="parentId", value = "家长id", dataType = "String", paramType = "query"),
    })
    @GetMapping(value = "/get-parent-status")
    public Msg getParentStatus(String parentId){
        if (!StringUtils.isNoneBlank(parentId))
            return Msg.success();
        String phone = parentService.getparentById(parentId).getParentVisitorPhone();
        JSONObject parentStatus = parentService.getParentStatus(phone);
        return Msg.success().add("parentStatus", parentStatus);
    }

    @ApiOperation(value = "查询某个用户公众号关注情况")
    @ApiImplicitParams({
            @ApiImplicitParam(name="uid", value = "用户id", dataType = "String", paramType = "query"),
    })
    @GetMapping(value = "/get-user-status")
    public Msg getUserStatus(String uid){
        if (StringUtils.isNoneBlank(uid)){
            String phone = null;
            if (uid.startsWith("1")){
                phone = userService.getUserByUid(uid).getMobile();
            }else if (uid.startsWith("3")){
                phone = parentService.getparentById(uid).getParentVisitorPhone();
            }
            JSONObject userStatus = parentService.getUserStatus(phone);
            return Msg.success().add("userStatus", userStatus);
        }else {
            return Msg.fail(ErrorEnum.E_90003, ErrorEnum.E_90003.getErrorMsg());
        }
    }

    @ApiOperation(value = "家长自主添加一个手机号码")
    @ApiImplicitParams({
            @ApiImplicitParam(name="uid", value = "用户id", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name="studentId", value = "学生id", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name="parentName", value = "家长姓名", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name="parentPhone", value = "家长电话", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name="parentType", value = "家长类型，是家长1还是家长2", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name="parentPhoneCode", value = "手机号码验证码", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name="parentPhoneCodeId", value = "手机号码验证码id", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name="parentPhoto", value = "家长照片", dataType = "String", paramType = "query"),
    })
    @GetMapping(value = "/parent-add-parent")
    public Msg parentAddParent(String uid, Integer studentId, String parentName, String parentPhone, String parentPhoto, Integer parentType, Integer parentPhoneCode, Integer parentPhoneCodeId){
        if (!compareVerifyCode(parentPhoneCodeId, parentPhoneCode)){
            return Msg.fail(ErrorEnum.E_101, "验证码错误，请重新输入！");
        }
        Integer schoolCode = studentService.getStudentSchoolCode(studentId);
        ParentVisitorEntity parent = new ParentVisitorEntity();
        parent.setParentVisitorType(parentType);
        parent.setParentVisitorName(parentName);
        parent.setParentVisitorSchoolCode(schoolCode);
        parent.setParentVisitorBase64(parentPhoto);
        parent.setParentVisitorPhone(parentPhone);
        Map<String, Object> map = addParent(studentId, parent);
        Integer code = (Integer) map.get("code");
        if (code == 0){
            return Msg.fail(ErrorEnum.E_101, (String) map.get("msg"));
        }else {
            return Msg.success();
        }
    }

    @ApiOperation(value = "查看家长登录到小程序概览")
    @ApiImplicitParams({
            @ApiImplicitParam(name="schoolCode", value = "学校id", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name="gradeId", value = "年级id", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name="classId", value = "班级id", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name="isExport", value = "是否需要导出，0不需要，1需要", dataType = "Integer", paramType = "query"),
    })
    @GetMapping(value = "/list-parent-register-rate")
    public Msg exportParentRegisterRate(HttpServletResponse response, Integer schoolCode, Integer gradeId, Integer classId, Integer isExport){
        List<ParentRegisterEntity> parentRegisterOverViewList = parentService.listParentRegisterOverView(schoolCode, gradeId, classId);
        ParentLoginOverviewEntity parentLoginOverview = parentService.getParentLoginOverview(schoolCode, gradeId, classId);
        if (isExport == 0){
            return Msg.success().add("parentRegisterOverViewList", parentRegisterOverViewList).add("parentLoginOverview", parentLoginOverview);
        }
        exportData(response, schoolCode, gradeId, classId, "家长登录概览");
        try {
            EasyExcel.write(response.getOutputStream(), ParentRegisterEntity.class).sheet("sheet1").doWrite(parentRegisterOverViewList);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Msg.success();
    }

    @ApiOperation(value = "查看家长登录到小程序详细（按学生统计）")
    @ApiImplicitParams({
            @ApiImplicitParam(name="schoolCode", value = "学校id", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name="gradeId", value = "年级id", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name="classId", value = "班级id", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name="isExport", value = "是否需要导出，0不需要，1需要", dataType = "Integer", paramType = "query", required = true),
    })
    @GetMapping(value = "/list-parent-register-detail")
    public Msg exportParentRegisterDetail(HttpServletResponse response, Integer schoolCode, Integer gradeId, Integer classId, Integer isExport){
        List<ParentRegisterStudentEntity> parentRegisterStudentList = parentService.listParentRegisterDetail(schoolCode, gradeId, classId);
        if (isExport == 0){
            return Msg.success().add("parentRegisterStudentList", parentRegisterStudentList);
        }
        exportData(response, schoolCode, gradeId, classId, "家长登录详细（按学生统计）");
        try {
            EasyExcel.write(response.getOutputStream(), ParentRegisterStudentEntity.class).sheet("sheet1").doWrite(parentRegisterStudentList);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Msg.success();
    }

    @ApiOperation(value = "查看家长登录到小程序详细（按家长统计）")
    @ApiImplicitParams({
            @ApiImplicitParam(name="schoolCode", value = "学校id", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name="gradeId", value = "年级id", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name="classId", value = "班级id", dataType = "Integer", paramType = "query"),
    })
    @GetMapping(value = "/list-all-parent-register-detail")
    public Msg exportALlParentRegisterDetail(HttpServletResponse response, Integer schoolCode, Integer gradeId, Integer classId, Integer isExport){
        List<ParentLoginEntity> parentLoginList = parentService.listParentLogin(schoolCode, gradeId, classId);
        exportData(response, schoolCode, gradeId, classId, "家长登录详细（按家长统计）");
        try {
            EasyExcel.write(response.getOutputStream(), ParentLoginEntity.class).sheet("sheet1").doWrite(parentLoginList);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Msg.success();
    }

    @ApiOperation(value = "查看学生家长信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name="schoolCode", value = "学校id", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name="gradeId", value = "年级id", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name="classId", value = "班级id", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name="isExport", value = "是否需要导出，0不需要，1需要", dataType = "Integer", paramType = "query"),
    })
    @GetMapping(value = "/list-student-parent-info")
    public Msg exportStudentParentInfo(HttpServletResponse response, Integer schoolCode, Integer gradeId, Integer classId, Integer isExport){
        List<ParentStudentInfoEntity> parentStudentInfoList = parentService.listParentStudentInfo(schoolCode, gradeId, classId);
        if (isExport == 0){
            return Msg.success().add("parentStudentInfoList", parentStudentInfoList);
        }
        exportData(response, schoolCode, gradeId, classId, "学生家长信息");
        try {
            EasyExcel.write(response.getOutputStream(), ParentStudentInfoEntity.class).sheet("sheet1").doWrite(parentStudentInfoList);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Msg.success();
    }

    private void exportData(HttpServletResponse response, Integer schoolCode, Integer gradeId, Integer classId, String tableName){
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = "";
        String schoolName = schoolService.getSchoolName(schoolCode);
        fileName += schoolName;
        if (gradeId != null){
            String gradeName = classService.getClassById(gradeId, schoolCode).getClassName();
            fileName += gradeName;
        }
        if (classId != null){
            String className = classService.getClassById(classId, schoolCode).getClassName();
            fileName += className;
        }
        Calendar calendar = Calendar.getInstance();
        fileName += tableName;
        fileName += new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
        try {
            fileName = URLEncoder.encode(fileName, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
    }



    /**
     * 分解邀请码
     * @return
     */
    private Map<String, Integer> readInvitationCode(String invitationCode){
        Map<String, Integer> map = new HashMap<>();
        //邀请码为16位
        // TODO 邀请码暂定为学校id+班级id，例如5101080001100100
        if(invitationCode.length() != 16){
            return null;
        }
        Integer schoolCode = Integer.valueOf(invitationCode.substring(0, 9));
        Integer classId = Integer.valueOf(invitationCode.substring(9));
        map.put("schoolCode", schoolCode);
        map.put("classId", classId);
        return map;
    }

    /**
     * 信息修改后通知老师
     * @param teacher
     * @param parentOrStudent 提示是家长信息修改还是学生信息修改
     */
    private void sendInformationChangeMessage(TeacherBasicInfoEntity teacher, String parentOrStudent){
        //查询班主任openid
        PubCountEntity pubCountEntity = messageService.getPubCountOpenidByPhone(teacher.getMobile());
        Integer schoolCode = userService.getSchoolCodeByUserId(teacher.getTeacherId());
        String schoolName = schoolService.getSchoolName(schoolCode);
        String[] paramsWeiXin = {"", schoolName, "系统通知",
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), parentOrStudent + "信息变更申请，请及时处理！" , ""};
        SendUtils.sendByWeixinAndPath(pubCountEntity, paramsWeiXin, pubCountEntity.getTemplateId(), "packageC/pages/student/studentscenter");
    }

    // 短信发给审核进度给家长
    private void sendToPerson(String phone, String templateId,String paramString) {
        String[] paramsMobile = new String[2];
        paramsMobile[0] = paramString;
        //适配该家长通知的短信模板
        paramsMobile[1] = "";
        logger.info("短信发送给家长显示信息审核进度:" + phone);
        SendUtils.sendByShortMessage(phone, paramsMobile,templateId);
    }

    private Map<String, Object> addParent(Integer studentId, ParentVisitorEntity parentVisitorEntity){
        int code;
        // 判断该生正在新增家长电话是否和另一个家长重复
        List<ParentVisitorEntity> parentList = parentService.listParentByStudentId(studentId);
        if(parentList.size() == 1 && parentList.get(0).getParentVisitorPhone().equals(parentVisitorEntity.getParentVisitorPhone())){
            return ApiReturnUtil.error("新增失败，该生两个家长电话号码不能相同！");
        }
        // 新增时需要判断是否该号码已存在
        ParentVisitorEntity temp = parentService.getParentByPhone(parentVisitorEntity.getParentVisitorPhone());
        String parent_visitor_id = "";
        if (temp == null){
            parent_visitor_id = ("3" + System.currentTimeMillis());
            parentVisitorEntity.setParentVisitorId(parent_visitor_id);
            code = parentService.insertParent(parentVisitorEntity);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("id", studentId);
        map.put("parent_id", temp == null ? parent_visitor_id : temp.getParentVisitorId());
        if (parentVisitorEntity.getParentVisitorType() == 1) {
            map.put("type", 1);
        } else {
            map.put("type", 2);
        }
        code = studentService.updateStuent1(map);
        if (code == 1) {
            return ApiReturnUtil.success("更新成功", "");
        }
        return ApiReturnUtil.error("更新失败");
    }

}
